// 编译阶段

#include <assert.h>
#include <stdexcept>
#include <iostream>

using namespace std;


/*
    用来控制编译器的编译指令 指示编译器如何做以便生成更高效的代码
    GCC中是__attribute__ 
    VC++中是__declspec
    C++11 中将其标准化 正式名称叫做【属性】可以理解为给变量、函数、类等语法组成部分
    贴上了编译阶段的标签方便编译器的识别和处理 C++11的属性并没有增加关键字 而是由
    [[]]组成 中间填写的是属性标签
    属性属于编译阶段编程 必须由编译器理解后处理 所以不能自定义属性标签只能等编译器开发者定义新属性
    参考
    https://zhuanlan.zhihu.com/p/392460397
    https://learn.microsoft.com/zh-cn/cpp/cpp/property-cpp
    https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
*/

[[noreturn]]    //函数绝不会返回任何值
[[deprecated("2023-08-01")]] //标记废弃的函数、变量和类
int func()
{
    throw runtime_error("no return error");
}

// GCC扩展属性
[[gnu::constructor]]
void before_main()
{
    cout << "before main!!!" << endl;
}

[[gnu::destructor]]
void after_main()
{
    cout << "before main!!!" << endl;
}
// 静态断言static_assert是关键字而不是宏 其是在编译阶段进行检测 不能对变量等只在运行期间存在的对象做检测，它是迈向模板元编程的第一步
// 动态断言assert是一个宏但在预处理阶段并不生效，在运行期间进行检测 
template <typename T> void foo1(T t)
{
    //C++17新增的断言模板参数的模板元函数
    static_assert(is_integral_v<T>);
    static_assert(is_pointer_v<T>);
    static_assert(is_constructible_v<T>);

    static_assert(sizeof(long) >= 8, "must run on x64");
    static_assert(sizeof(int) == 4, "int must be 32bit");
}

int main()
{
    cout << "main!!!" << endl;
    // int a = 32;
    // foo1(a);


}